﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using JpLabs.Extensions;
using System.ServiceModel;
using DistributedGame.Service;

namespace DistributedGame
{
	public class ValueChangedEventArgs<T> : EventArgs
	{
		public ValueChangedEventArgs(T oldValue, T newValue)
		{
			OldValue = oldValue;
			NewValue = newValue;
		}
		
		public T NewValue { get; private set; }
		public T OldValue { get; private set; }
		
		private bool? didValueChanged;
		public bool DidValueChanged
		{
			get {
				if (didValueChanged == null) didValueChanged = object.Equals(OldValue, NewValue);
				return didValueChanged.Value;
			}
		}
	}

	public class CommObjWatcher
	{
		private readonly ICommunicationObject commObj;
		private CommunicationState lastState;
		
		public CommObjWatcher(ICommunicationObject commObj)
		{
			this.commObj = commObj;
			this.lastState = commObj.State;

			commObj.Closed	+= delegate { this.OnStateChanged(CommunicationState.Closed); };
			commObj.Closing	+= delegate { this.OnStateChanged(CommunicationState.Closing); };
			commObj.Faulted	+= delegate { this.OnStateChanged(CommunicationState.Faulted); };
			commObj.Opened	+= delegate { this.OnStateChanged(CommunicationState.Opened); };
			commObj.Opening	+= delegate { this.OnStateChanged(CommunicationState.Opening); };
		}

		private void OnStateChanged(CommunicationState newState)
		{
			var evArgs = new ValueChangedEventArgs<CommunicationState>(lastState, newState);
			this.lastState = newState;
			StateChanged.RaiseEvent(commObj, evArgs);
		}

		public event EventHandler<ValueChangedEventArgs<CommunicationState>> StateChanged;
	}

	internal static class MessageFormatter
	{
		public static string WelcomeMessage(string nickname)
		{
			return string.Format("Welcome, {0}!", nickname);
		}

		public static string ClientJoinedMessage(string nickname)
		{
			return string.Format("{0} has joined", nickname);
		}

		//public static string HostMessage(string text, string hostName)
		//{
		//    return string.Format("{{{0}}} {1}", hostName, text);
		//}

		//public static string ClientMessage(string text, string clientNickname)
		//{
		//    return string.Format("<{0}> {1}", clientNickname, text);
		//}

		public static string ClientIsDisconnectingMessage(string nickname)
		{
			return string.Format("* {0} is disconnecting", nickname);
		}

		public static string Message(RemoteMessage systemMessage)
		{
			var clientMessage = systemMessage as ClientMessage;
			if (clientMessage != null) {
				string format = (clientMessage.Sender.IsHost) ? "{{{0}}} {1}" : "<{0}> {1}";

			    return string.Format(format, clientMessage.Sender.Nickname, clientMessage.Content);
			} else {
				return string.Concat("* ", systemMessage.Content);
			}
		}
	}
}
